Skip to content

refactor(home): redesign hackathon top bar with aurora gradient style#72

Open
dethan3 wants to merge 2 commits intomainfrom
labor-hackathon-2026
Open

refactor(home): redesign hackathon top bar with aurora gradient style#72
dethan3 wants to merge 2 commits intomainfrom
labor-hackathon-2026

Conversation

@dethan3
Copy link
Copy Markdown
Member

@dethan3 dethan3 commented Apr 30, 2026

PR-72 PR-72 PR-72 Powered by Pull Request Badge

Checklist(清单):

  • Labels
  • Assignees
  • Reviewers
  1. 增加首页活动横幅
  2. pnpm-lock.yaml 有变动导致 eslint.config.ts:29@next/next 插件类型不匹配

Summary by CodeRabbit

发布说明

  • 新功能
    • 在首页添加黑客马拉松宣传顶部栏(可关闭)。
    • 顶部栏含本地化文本、活动链接和移动端优化显示。
    • 自动根据导航栏高度调整间距并在窗口大小变化时更新。
  • 样式
    • 顶部栏采用粘性定位、渐变与交互态样式。
  • 改进
    • 导航品牌与顶级链接禁止换行以保持布局稳定。

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

📝 Walkthrough

Walkthrough

在首页引入并渲染新的 PromoBar 组件;该组件在挂载时读取导航栏高度并通过 CSS 变量调整定位,使用 ResizeObserver/窗口尺寸监听保持同步,并异步请求活动数据以在横幅中显示(可关闭,关闭后隐藏)。

Changes

Cohort / File(s) Summary
首页集成
pages/index.tsx
在首页顶部(紧随 PageHead)新增 PromoBar 组件的导入与渲染。
推广栏实现
components/Activity/PromoBar.tsx
新增导出组件 PromoBar:内部管理可见性、基于导航栏高度设置 CSS 自定义属性、使用 ResizeObserver 与 window resize 同步、异步通过 ActivityModel 拉取活动并渲染可关闭的 Alert 横幅。
推广栏样式
components/Activity/PromoBar.module.less
新增 LESS 模块,包含粘性定位、渐变样式、响应式布局、交互态样式及移动端优化。
导航样式调整
components/Navigator/MainNavigator.tsx
为品牌与顶级导航链接加入 text-nowrap 类以防换行,样式逻辑保留。

Sequence Diagram(s)

sequenceDiagram
  participant User as 用户
  participant Home as 首页(pages/index)
  participant Promo as PromoBar 组件
  participant NavDOM as nav DOM
  participant Activity as ActivityModel
  User->>Home: 访问首页
  Home->>Promo: 渲染 PromoBar
  Promo->>NavDOM: 查询 nav 高度
  NavDOM-->>Promo: 返回高度
  Promo->>Promo: 设置 CSS 变量(--promo-top/--promo-margin)
  Promo->>NavDOM: 注册 ResizeObserver / window.resize 监听
  Promo->>Activity: 异步请求活动数据(fetchById)
  Activity-->>Promo: 返回活动数据
  Promo->>Home: 渲染 Alert 横幅(包含链接/事件名/关闭按钮)
  User->>Promo: 点击关闭
  Promo->>Promo: 更新本地 state 隐藏横幅
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

enhancement

Suggested reviewers

  • TechQuery

总体概述

主页添加了黑客马拉松推广顶栏,由 React 状态控制其显隐。组件使用 useEffect 计算相邻导航栏高度并动态更新 CSS 自定义属性调整栏的间距;支持窗口尺寸变化监听,暂未持久化关闭状态。

变更清单

群组 / 文件(s) 变更摘要
主页推广栏
pages/index.tsx
新增黑客马拉松推广顶栏组件,使用状态管理控制显隐;集成 ResizeObserver 动态计算导航栏高度并更新 CSS 自定义属性;注意 UI 文本需统一使用 t() 实现国际化;localStorage 持久化逻辑已注释,需确认产品需求。

代码审查要点

  1. 国际化完整性 — 验证推广栏的所有文本(标题、描述、按钮、辅助链接)是否通过 t() 函数完整国际化,避免硬编码字符串。
  2. React Bootstrap 使用一致性 — 确认组件使用的布局/控件是否遵循项目中统一的 React Bootstrap 方案(栅格、间距、Alert/CloseButton 等)。
  3. MobX 与数据层一致性 — 若 ActivityModel 使用 MobX,检查 observable/action/computed 的使用是否正确,以及在组件中订阅数据时是否使用 observer(若需响应式更新)。
  4. TypeScript 强类型 — 为 state、refs、ResizeObserver 回调和异步结果添加明确类型注解,避免 any。
  5. 资源与性能 — 确认 ResizeObserver 与 window resize 在卸载时已清理,避免多余重渲染;使用 next/image 的场景保持最佳实践。
  6. 错误处理与网络层统一 — ActivityModel 的异常捕获是否与项目的 web-utility / 统一错误处理、GitHub API 认证策略一致;日志不要泄露敏感信息。
  7. 无障碍与键盘支持 — 关闭按钮应可通过键盘操作并包含合适的 ARIA 标签。
  8. 样式变量与设计系统对齐 — 校验 CSS 自定义属性命名与全局样式体系一致,移动端文本换行/截断符合设计要求。
  9. 持久化策略确认 — localStorage 持久化逻辑被注释:需与产品确认是否保存关闭状态及存储键/过期策略。

审查工作量评估

🎯 3 (Moderate) | ⏱️ ~20 分钟

庆祝诗句

🎉 顶栏新秀现代码,
ResizeObserver 护周到,
活动数据异步回,
一键关闭界面好,
React 与样式并肩跳 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 标题清晰准确地反映了主要变更:在首页添加带有极光渐变样式的黑客马拉松顶部横幅(PromoBar 组件)。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch labor-hackathon-2026
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch labor-hackathon-2026

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@dethan3 dethan3 requested a review from TechQuery April 30, 2026 09:26
@dethan3 dethan3 added the feature New feature or request label Apr 30, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pages/index.tsx`:
- Line 69: Replace the hardcoded event name inside the span (className
styles.hackathonTopBarEventName) with a call to the i18n t() function and add a
corresponding translation key (e.g. "hackathon.eventName") to your locale files;
update pages/index.tsx to use t('hackathon.eventName') (or the chosen key) so
the visible text is localized and ensure the new key exists in all supported
locales.
- Around line 57-84: The top-banner uses raw HTML elements and a hard-coded
event name; replace the <aside>/<div>/<a>/<button>/<span> usage with React
Bootstrap components (e.g., Alert, Card, Button/CloseButton) while preserving
behavior tied to isHackathonTopBarVisible, hackathonTopBarStyle,
HackathonTopBarLink and the closeHackathonTopBar handler, and move the literal
"Labor AI Hackathon 2026" into i18n as home_hackathon_top_bar_event_name,
rendering it via t('home_hackathon_top_bar_event_name') alongside the existing
t('home_hackathon_top_bar_title'), t('home_hackathon_top_bar_description') and
t('home_hackathon_top_bar_action'); ensure aria-label/title still use
t('home_hackathon_top_bar_aria_label') and t('home_hackathon_top_bar_close').
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: afcd89f5-d1e7-40d2-bfc2-16789a915968

📥 Commits

Reviewing files that changed from the base of the PR and between b160b03 and 3b66c69.

⛔ Files ignored due to path filters (6)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml and included by none
  • styles/Home.module.less is excluded by none and included by none
  • styles/globals.css is excluded by none and included by none
  • translation/en-US.ts is excluded by none and included by none
  • translation/zh-CN.ts is excluded by none and included by none
  • translation/zh-TW.ts is excluded by none and included by none
📒 Files selected for processing (1)
  • pages/index.tsx

Comment thread pages/index.tsx Outdated
Comment thread pages/index.tsx Outdated
Comment thread styles/globals.css Outdated
Comment thread translation/zh-CN.ts
Comment on lines +34 to +37
home_hackathon_top_bar_aria_label: 'Labor AI Hackathon 2026 活动宣传',
home_hackathon_top_bar_badge: '活动招募中',
home_hackathon_top_bar_title: '打工人の终极反叛',
home_hackathon_top_bar_description: '48 小时,来这里创造未来',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不要硬编码任何来自数据库的数据。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是指从多维表格中取得数据吗?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是指从多维表格中取得数据吗?

是,直接照抄我以前写的代码:
https://github.com/kaiyuanshe/kaiyuanshe.github.io/blob/a9afddbee79d1e3fe501d491d2aa7f0699ac56c9/pages/index.tsx#L99-L124

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我尝试了代码复用,但是没有拿到 name 的数据,麻烦 @TechQuery 再帮我看一下代码

Comment thread pages/index.tsx
- Replace raw HTML with Alert, Alert.Link, CloseButton

- Move complex styles from styled-jsx to PromoBar.module.less

- Add Bootstrap utility classes for layout

- Fetch activity name/link from Lark Bitable via ActivityModel

- Keep localStorage persistence commented out
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/Activity/PromoBar.tsx`:
- Around line 41-50: 在 useEffect 中对异步加载添加卸载保护:在 useEffect 里创建一个标志(例如 let mounted
= true 或使用 AbortController 如果 ActivityModel.getOne 支持取消),在 getOne
调用前保留该标志/控制器,并在 Promise resolve 前检查 mounted,只有 mounted 为 true 时才调用 setActivity;在
useEffect 返回的 cleanup 函数将 mounted 设为 false(或调用
controller.abort())以阻止组件卸载后继续更新或消耗请求资源。确保引用的符号为 useEffect、ActivityModel.getOne 和
setActivity。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4a3b4906-bb3f-4728-9d11-7adac39ad05a

📥 Commits

Reviewing files that changed from the base of the PR and between 3b66c69 and ed2cf15.

📒 Files selected for processing (4)
  • components/Activity/PromoBar.module.less
  • components/Activity/PromoBar.tsx
  • components/Navigator/MainNavigator.tsx
  • pages/index.tsx
✅ Files skipped from review due to trivial changes (3)
  • pages/index.tsx
  • components/Activity/PromoBar.module.less
  • components/Navigator/MainNavigator.tsx

Comment on lines +41 to +50
useEffect(() => {
(async () => {
try {
const model = new ActivityModel();
const data = await model.getOne('Labor-AI-hackathon-2026');
setActivity(data);
} catch (err) {
console.error('Failed to load activity:', err);
}
})();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

补上异步加载的卸载保护。

getOne() 可能在组件卸载后才返回,当前代码会继续 setActivity,留下陈旧更新并浪费请求资源。

♻️ 建议修复
 useEffect(() => {
+  let cancelled = false;
+
   (async () => {
     try {
       const model = new ActivityModel();
       const data = await model.getOne('Labor-AI-hackathon-2026');
-      setActivity(data);
+      if (!cancelled) setActivity(data);
     } catch (err) {
+      if (cancelled) return;
       console.error('Failed to load activity:', err);
     }
   })();
+
+  return () => {
+    cancelled = true;
+  };
 }, []);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/Activity/PromoBar.tsx` around lines 41 - 50, 在 useEffect
中对异步加载添加卸载保护:在 useEffect 里创建一个标志(例如 let mounted = true 或使用 AbortController 如果
ActivityModel.getOne 支持取消),在 getOne 调用前保留该标志/控制器,并在 Promise resolve 前检查
mounted,只有 mounted 为 true 时才调用 setActivity;在 useEffect 返回的 cleanup 函数将 mounted
设为 false(或调用 controller.abort())以阻止组件卸载后继续更新或消耗请求资源。确保引用的符号为
useEffect、ActivityModel.getOne 和 setActivity。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants